package cn.murky.socketd;

import cn.murky.common.constant.CommonErrorConstant;
import cn.murky.common.record.ErrorRecord;
import lombok.Data;
import lombok.experimental.Accessors;
import org.noear.snack.ONode;
import org.noear.snack.annotation.ONodeAttr;
import org.noear.socketd.transport.core.Message;
import org.noear.socketd.transport.core.Session;
import org.noear.socketd.transport.core.entity.StringEntity;
import org.noear.solon.Solon;
import org.noear.solon.core.handle.Context;
import org.noear.solon.i18n.I18nUtil;

import java.io.IOException;
import java.io.Serial;
import java.io.Serializable;
import java.util.Locale;
import java.util.Map;

/**
 * Socketd响应体数据结构
 *
 * @param <T> 任意类型
 * @auth hans
 */
@Accessors(chain = true)
@Data
public class SdResult<T> implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;
    @ONodeAttr(ignore=true)
    private static final transient String LANGGUAGE_COLUMN="Language";
    @ONodeAttr(ignore=true)
    private static final transient String RENDER_NAME="@json";

    /**
     * 响应码
     */
    private int code;
    /**
     * 消息内容
     */
    private String message;
    /**
     * 响应数据
     */
    private T result;

    public static <T> void replyEndOk(T data, Session session, Message message) throws IOException {
        SdResult<T> tSdResult = restResult(data, session);
        session.replyEnd(message, new StringEntity(parseJson(tSdResult)));
    }

    public static <T> void replyEndOk( Session session, Message message) throws IOException {
        SdResult<T> tSdResult = restResult(null, session);
        session.replyEnd(message, new StringEntity(parseJson(tSdResult)));
    }

    public static <T> void replyEndFail(Session session, Message message) throws IOException {
        SdResult<T> tSdResult = restResult(CommonErrorConstant.FAIL,null, session);
        session.replyEnd(message, new StringEntity(parseJson(tSdResult)));
    }

    public static <T> void replyEndFail(Session session, Message message,String msg) throws IOException {
        SdResult<T> tSdResult = restResultFail(msg, session);
        session.replyEnd(message, new StringEntity(parseJson(tSdResult)));
    }

    /**
     * 发送(发送消息后不等待)
     * @param data 需要发送的数据
     * @param session 发送的session
     * @param event 发送的事件
     */
    public static <T> void send(T data, Session session, String event) throws IOException {
        SdResult<T> tSdResult = restResult(data, session);
        session.send(event, new StringEntity(parseJson(tSdResult)));
    }

    private static <T> SdResult<T> restResult(T data, Session session) {
        Map<String, String> paramMap = session.handshake().paramMap();
        String lang = paramMap.get(LANGGUAGE_COLUMN);
        SdResult<T> SdResult = new SdResult<>();
        SdResult.setCode(CommonErrorConstant.SUCCESS.errCode());
        SdResult.setResult(data);
        SdResult.setMessage(I18nUtil.getMessage(Locale.of(lang), CommonErrorConstant.SUCCESS.message()));
        return SdResult;
    }

    private static <T> SdResult<T> restResult(ErrorRecord errorRecord,T data, Session session) {
        Map<String, String> paramMap = session.handshake().paramMap();
        String lang = paramMap.get(LANGGUAGE_COLUMN);
        SdResult<T> SdResult = new SdResult<>();
        SdResult.setCode(errorRecord.errCode());
        SdResult.setResult(data);
        SdResult.setMessage(I18nUtil.getMessage(Locale.of(lang), errorRecord.message()));
        return SdResult;
    }

    private static <T> SdResult<T> restResultFail(String msg, Session session) {
        SdResult<T> SdResult = new SdResult<>();
        SdResult.setCode(CommonErrorConstant.FAIL.errCode());
        SdResult.setMessage(msg);
        return SdResult;
    }

    private static <T> String parseJson(SdResult<T> data) {
        try {
            return Solon.app().render(RENDER_NAME).renderAndReturn(data, Context.current());
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
}
